package com.wormhole.wormholemanagement.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.imaging.ImageFormat;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImagingException;
import org.apache.commons.imaging.common.ImageMetadata;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
public class ExifWriterUtil {

    public static void main(String[] args) {
        try {
            File file = new File("D:\\相片档案\\R-C.gif"); // 确保是JPEG文件
            File file1=convertPngToJpegAndReplace(file);
//           File file1=convertPngToJpegAndReplace(new File("/Users/steven/tools/test.png"));
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
//            File file1= convertToJpegAndReplace(new File("D:\\相片档案\\2025\\9月\\0901\\军训\\20240603164433.bmp"));
            updateJpegMetadata(file1, "测试","","demoName", formatter.format(new Date()));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将PNG图片转换为JPEG格式并替换原文件
     */
    public static File convertPngToJpegAndReplace(File pngFile) throws Exception {
        // 读取PNG图片
        BufferedImage bufferedImage = ImageIO.read(pngFile);

        // 创建新的JPEG缓冲图像（背景为白色）
        BufferedImage bufferedImage1 = new BufferedImage(
                bufferedImage.getWidth(),
                bufferedImage.getHeight(),
                BufferedImage.TYPE_INT_RGB
        );
        bufferedImage1.createGraphics().drawImage(bufferedImage, 0, 0, Color.WHITE, null);

        // 定义输出路径为原文件路径，仅更改扩展名为.jpg
        String outputJpegPath = pngFile.getAbsolutePath().replaceFirst("\\.[^.]+$", ".jpg");

        // 写入JPEG文件
        try (FileOutputStream fos = new FileOutputStream(outputJpegPath)) {
            ImageIO.write(bufferedImage1, "jpg", fos);
            fos.flush();
        }

        // 删除原PNG文件
        if (!pngFile.delete()) {
            System.out.println("无法删除原PNG文件: " + pngFile.getAbsolutePath());
        }

        System.out.println("PNG已转换为JPEG并替换原文件: " + outputJpegPath);
        return new File(outputJpegPath);
    }

    /**
     * 将任意图片格式转换为JPEG格式并替换原文件
     */
    public static File convertToJpegAndReplace(File inputFile) throws Exception {
        // 读取图片
        BufferedImage bufferedImage = ImageIO.read(inputFile);

        if (bufferedImage == null) {
            throw new IllegalArgumentException("无法读取图片: " + inputFile.getAbsolutePath());
        }

        // 创建新的JPEG缓冲图像（背景为白色）
        BufferedImage jpegBufferedImage = new BufferedImage(
                bufferedImage.getWidth(),
                bufferedImage.getHeight(),
                BufferedImage.TYPE_INT_RGB
        );
        jpegBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0, Color.WHITE, null);

        // 定义输出路径为原文件路径，仅更改扩展名为.jpg
        String outputJpegPath = inputFile.getAbsolutePath().replaceFirst("\\.[^.]+$", ".jpg");

        // 写入JPEG文件
        try (FileOutputStream fos = new FileOutputStream(outputJpegPath)) {
            ImageIO.write(jpegBufferedImage, "jpg", fos);
            fos.flush();
        }

        // 删除原文件
        if (!inputFile.delete()) {
            System.out.println("无法删除原文件: " + inputFile.getAbsolutePath());
        }

        System.out.println("图片已转换为JPEG并替换原文件: " + outputJpegPath);
        return new File(outputJpegPath);
    }


    /**
     * 根据图片格式自动处理元数据（通用方法）
     * @param file 原始图片文件
     * @param author 作者信息
     * @param dateTime 日期时间信息 (格式: yyyy:MM:dd HH:mm:ss)
     */
    public static void updateImageMetadata(File file, String title,String author, String dateTime) throws Exception {
        if (!file.exists()) {
            System.out.println("文件不存在: " + file.getAbsolutePath());
            return;
        }

        // 获取文件格式
        ImageFormat format = Imaging.guessFormat(file);
        System.out.println("处理文件: " + file.getName() + ", 格式: " + format.getName());

        // 根据不同格式处理
        switch (format.getName().toLowerCase()) {
            case "jpeg":
            case "jpg":
                updateJpegMetadata(file, title,author,author, dateTime);
                break;
            case "png":
                updatePngMetadata(file, author, dateTime);
                break;
            case "tiff":
            case "tif":
                updateTiffMetadata(file, author, dateTime);
                break;
            case "bmp":
                updateBmpMetadata(file, author, dateTime);
                break;
            case "gif":
                updateGifMetadata(file, author, dateTime);
                break;
            default:
                System.out.println("不支持的格式或该格式不支持元数据写入: " + format.getName());
                break;
        }
    }
    /**
     * 更新JPEG图片的EXIF元数据（直接覆盖原文件）
     * 增强版本，包含更好的错误处理
     */
    public static void updateJpegMetadata(File file, String title, String unitName,String author, String dateTime) throws Exception {
        // 检查文件是否存在
        if (!file.exists()) {
            System.out.println("文件不存在: " + file.getAbsolutePath());
            return;
        }

        // 验证文件是否为有效的JPEG文件
        if (!isValidJpegFile(file)) {
            System.out.println("文件不是有效的JPEG文件: " + file.getAbsolutePath());
            return;
        }

        TiffOutputSet outputSet = null;

        try {
            // 尝试获取元数据
            ImageMetadata metadata = Imaging.getMetadata(file);

            if (metadata instanceof JpegImageMetadata) {
                JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
                TiffImageMetadata exif = jpegMetadata.getExif();

                if (exif != null) {
                    try {
                        // 尝试获取原有EXIF数据
                        outputSet = exif.getOutputSet();
                    } catch (ImagingException e) {
                        // 如果原有数据存在编码问题，创建新的输出集
                        if (e.getMessage() != null && e.getMessage().contains("Text field not encoded as bytes")) {
                            System.out.println("原有EXIF数据存在编码问题，将创建新的元数据集");
                            outputSet = new TiffOutputSet();
                        } else {
                            // 其他异常，也创建新的输出集
                            System.out.println("EXIF数据读取异常，创建新的元数据集: " + e.getMessage());
                            outputSet = new TiffOutputSet();
                        }
                    } catch (Exception e) {
                        // 捕获其他所有异常
                        System.out.println("读取EXIF数据时发生未知错误，创建新的元数据集: " + e.getMessage());
                        outputSet = new TiffOutputSet();
                    }
                }
            }
        } catch (IllegalArgumentException e) {
            // 捕获数组读取错误
            System.out.println("读取图像元数据时发生数据错误，文件可能已损坏: " + file.getAbsolutePath());
            System.out.println("错误详情: " + e.getMessage());
            // 创建一个新的空的元数据集
            outputSet = new TiffOutputSet();
        } catch (Exception e) {
            // 捕获其他所有异常
            System.out.println("读取图像元数据时发生未知错误: " + e.getMessage());
            outputSet = new TiffOutputSet();
        }

        // 如果没有EXIF数据，创建新的
        if (outputSet == null) {
            outputSet = new TiffOutputSet();
        }

        try {
            // 获取根目录并添加作者信息
            TiffOutputDirectory rootDirectory = outputSet.getOrCreateRootDirectory();
            TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory();

            // 清理并添加作者信息
            if (author != null && !author.isEmpty()) {
                rootDirectory.removeField(TiffTagConstants.TIFF_TAG_ARTIST);
                rootDirectory.add(TiffTagConstants.TIFF_TAG_ARTIST, unitName + " " +author);
            }else{
                rootDirectory.removeField(TiffTagConstants.TIFF_TAG_ARTIST);
                rootDirectory.add(TiffTagConstants.TIFF_TAG_ARTIST, unitName);
            }

            // 清理并添加时间信息
//            if (dateTime != null && !dateTime.isEmpty()) {
//                exifDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
//                exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, dateTime);
//
//                exifDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED);
//                exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED, dateTime);
//            }

            // 清理并添加标题信息
            if (title != null && !title.isEmpty()) {
                rootDirectory.removeField(TiffTagConstants.TIFF_TAG_IMAGE_DESCRIPTION);
                rootDirectory.add(TiffTagConstants.TIFF_TAG_IMAGE_DESCRIPTION, title);
            }

            // 创建临时文件用于写入修改后的元数据
            File tempFile = new File(file.getParent(), file.getName() + ".tmp");

            // 使用更安全的方式处理文件写入
            try (OutputStream os = new FileOutputStream(tempFile)) {
                try {
                    new ExifRewriter().updateExifMetadataLossless(file, os, outputSet);
                } catch (Exception e) {
                    // 如果updateExifMetadataLossless失败，尝试其他方法
                    System.out.println("updateExifMetadataLossless失败，尝试替代方法: " + e.getMessage());
                    throw e; // 重新抛出异常，让上层处理
                }
            }

            // 确保临时文件已生成且大小合理
            if (!tempFile.exists() || tempFile.length() == 0) {
                throw new RuntimeException("临时文件未生成或为空: " + tempFile.getAbsolutePath());
            }

            // 删除原文件
            if (!file.delete()) {
                // 如果删除失败，尝试重命名原文件作为备份
                File backupFile = new File(file.getParent(), file.getName() + ".bak");
                if (backupFile.exists()) {
                    backupFile.delete();
                }
                if (!file.renameTo(backupFile)) {
                    throw new RuntimeException("无法删除或备份原文件: " + file.getAbsolutePath());
                }
            }

            // 将临时文件重命名为原文件名
            if (!tempFile.renameTo(file)) {
                throw new RuntimeException("无法重命名临时文件为原文件名: " + file.getAbsolutePath());
            }

            System.out.println("JPEG EXIF元数据已更新，已覆盖原文件: " + file.getAbsolutePath());

        } catch (Exception e) {
            System.out.println("更新JPEG元数据时发生错误: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }
    /**
     * 验证JPEG文件是否有效
     */
    private static boolean isValidJpegFile(File file) {
        try {
            BufferedImage image = ImageIO.read(file);
            return image != null;
        } catch (Exception e) {
            return false;
        }
    }
    /**
     * 备用方法：如果updateExifMetadataLossless失败，使用此方法重建JPEG文件
     */
    public static void rebuildJpegWithMetadata(File file, String title,String unitName,String author, String dateTime) throws Exception {
        try {
            // 读取原始图像
            BufferedImage image = ImageIO.read(file);
            if (image == null) {
                throw new IllegalArgumentException("无法读取图像文件");
            }

            // 创建新的EXIF数据
            TiffOutputSet outputSet = new TiffOutputSet();
            TiffOutputDirectory rootDirectory = outputSet.getOrCreateRootDirectory();
            TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory();

            // 添加元数据
            if (author != null && !author.isEmpty()) {
                rootDirectory.add(TiffTagConstants.TIFF_TAG_ARTIST,unitName+" "+author);
            }else{
                rootDirectory.add(TiffTagConstants.TIFF_TAG_ARTIST, unitName);
            }

            if (dateTime != null && !dateTime.isEmpty()) {
                exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, dateTime);
                exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED, dateTime);
            }

            if (title != null && !title.isEmpty()) {
                rootDirectory.add(TiffTagConstants.TIFF_TAG_IMAGE_DESCRIPTION, title);
            }

            // 创建临时文件
            File tempFile = new File(file.getParent(), file.getName() + ".tmp");

            // 重新写入JPEG文件并嵌入EXIF数据
            try (OutputStream os = new FileOutputStream(tempFile)) {
                // 使用Apache Commons Imaging写入带EXIF的JPEG
                Imaging.writeImage(image, os, ImageFormats.JPEG);
            }

            // 替换原文件
            if (!file.delete()) {
                throw new RuntimeException("无法删除原文件: " + file.getAbsolutePath());
            }

            if (!tempFile.renameTo(file)) {
                throw new RuntimeException("无法重命名临时文件: " + file.getAbsolutePath());
            }

            System.out.println("JPEG文件已重建并添加元数据: " + file.getAbsolutePath());
        } catch (Exception e) {
            System.out.println("重建JPEG文件时发生错误: " + e.getMessage());
            throw e;
        }
    }


    /**
     * 更新PNG图片的文本元数据
     */
    public static void updatePngMetadata(File file, String author, String dateTime) throws Exception {

        // BMP格式本身不支持EXIF或复杂的元数据
        // 可以考虑转换为JPEG或PNG格式
        convertToJpegWithMetadata(file, author, dateTime);
    }
    /**
     * 更新TIFF图片的元数据
     */
    public static void updateTiffMetadata(File file, String author, String dateTime) throws Exception {
        // 获取元数据
        ImageMetadata metadata = Imaging.getMetadata(file);
        TiffOutputSet outputSet = null;

        if (metadata instanceof TiffImageMetadata) {
            TiffImageMetadata tiffMetadata = (TiffImageMetadata) metadata;
            outputSet = tiffMetadata.getOutputSet();
        }

        // 如果没有元数据，创建新的
        if (outputSet == null) {
            outputSet = new TiffOutputSet();
        }

        // 获取根目录并添加作者信息
        TiffOutputDirectory rootDirectory = outputSet.getOrCreateRootDirectory();

        // 添加或更新作者信息
        if (author != null && !author.isEmpty()) {
            rootDirectory.removeField(TiffTagConstants.TIFF_TAG_ARTIST);
            rootDirectory.add(TiffTagConstants.TIFF_TAG_ARTIST, author);
        }

        // 添加或更新时间信息
        if (dateTime != null && !dateTime.isEmpty()) {
            rootDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
            rootDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED);

            rootDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, dateTime);
        }

        // 创建输出文件
        File outputFile = new File(file.getParent(),
                file.getName().replaceFirst("\\.[^.]+$", "") + "_modified" +
                        file.getName().substring(file.getName().lastIndexOf(".")));

        // 写入修改后的文件（TIFF需要完全重写）
        try (OutputStream os = new FileOutputStream(outputFile)) {
            Imaging.writeImage(Imaging.getBufferedImage(file), os, ImageFormats.TIFF);
        }

        System.out.println("TIFF元数据已更新，保存到: " + outputFile.getAbsolutePath());
    }

    /**
     * 将文件转换为标准JPEG格式
     */
    public static File convertToStandardJpeg(File inputFile) throws Exception {
        try {
            // 读取图片
            BufferedImage bufferedImage = ImageIO.read(inputFile);
            if (bufferedImage == null) {
                throw new IllegalArgumentException("无法读取图片: " + inputFile.getAbsolutePath());
            }

            // 创建新的JPEG缓冲图像（背景为白色）
            BufferedImage jpegBufferedImage = new BufferedImage(
                    bufferedImage.getWidth(),
                    bufferedImage.getHeight(),
                    BufferedImage.TYPE_INT_RGB
            );

            Graphics2D g2d = jpegBufferedImage.createGraphics();
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, jpegBufferedImage.getWidth(), jpegBufferedImage.getHeight());
            g2d.drawImage(bufferedImage, 0, 0, null);
            g2d.dispose();

            // 定义输出路径为原文件路径，仅更改扩展名为.jpg
            String outputJpegPath = inputFile.getAbsolutePath().replaceFirst("\\.[^.]+$", ".jpg");

            // 写入JPEG文件
            try (FileOutputStream fos = new FileOutputStream(outputJpegPath)) {
                ImageIO.write(jpegBufferedImage, "jpg", fos);
                fos.flush();
            }

            System.out.println("图片已转换为标准JPEG: " + outputJpegPath);
            return new File(outputJpegPath);
        } catch (Exception e) {
            System.out.println("转换为标准JPEG时发生错误: " + e.getMessage());
            throw e;
        }
    }
    /**
     * 更新BMP图片的元数据（BMP格式元数据支持有限）
     */
    public static void updateBmpMetadata(File file, String author, String dateTime) throws Exception {
        System.out.println("BMP格式元数据支持有限，无法直接写入作者和日期信息。");
        System.out.println("建议转换为JPEG或PNG格式以支持完整的元数据功能。");

        // BMP格式本身不支持EXIF或复杂的元数据
        // 可以考虑转换为JPEG或PNG格式
        convertToJpegWithMetadata(file, author, dateTime);
    }

    /**
     * 更新GIF图片的元数据（GIF格式元数据支持有限）
     */
    public static void updateGifMetadata(File file, String author, String dateTime) throws Exception {
        System.out.println("GIF格式元数据支持有限，无法直接写入作者和日期信息。");
        System.out.println("建议转换为JPEG或PNG格式以支持完整的元数据功能。");

        // GIF格式本身不支持EXIF
        // 可以考虑转换为JPEG或PNG格式
        convertToJpegWithMetadata(file, author, dateTime);
    }

    /**
     * 将其他格式转换为JPEG并添加元数据
     */
    private static void convertToJpegWithMetadata(File sourceFile, String author, String dateTime) throws Exception {
        // 获取源文件的元数据
        ImageMetadata metadata = Imaging.getMetadata(sourceFile);

        // 创建TIFF输出集
        TiffOutputSet outputSet = new TiffOutputSet();
        TiffOutputDirectory rootDirectory = outputSet.getOrCreateRootDirectory();

        // 添加元数据
        if (author != null && !author.isEmpty()) {
            rootDirectory.add(TiffTagConstants.TIFF_TAG_ARTIST, author);
        }

        if (dateTime != null && !dateTime.isEmpty()) {
            rootDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, dateTime);
        }

        // 创建输出文件
        String outputFileName = sourceFile.getName().replaceFirst("\\.[^.]+$", "") + "_converted.jpg";
        File outputFile = new File(sourceFile.getParent(), outputFileName);

        // 转换为JPEG并添加元数据
        try (OutputStream os = new FileOutputStream(outputFile)) {
            Imaging.writeImage(Imaging.getBufferedImage(sourceFile), os, ImageFormats.JPEG);
        }

        System.out.println("文件已转换为JPEG格式并添加元数据，保存到: " + outputFile.getAbsolutePath());
    }

    public static void addOrUpdateExifData(File file, String author, String dateTime) throws Exception {
        // 检查文件是否存在
        if (!file.exists()) {
            System.out.println("文件不存在: " + file.getAbsolutePath());
            return;
        }

        // 获取元数据
        ImageMetadata metadata = Imaging.getMetadata(file);

        TiffOutputSet outputSet = null;

        if (metadata instanceof JpegImageMetadata) {
            JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
            TiffImageMetadata exif = jpegMetadata.getExif();

            if (exif != null) {
                outputSet = exif.getOutputSet();
            }
        }

        // 如果没有EXIF数据，创建新的
        if (outputSet == null) {
            outputSet = new TiffOutputSet();
        }

        // 获取或创建EXIF目录
//        TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory();

        // 添加或更新作者信息
//        if (author != null && !author.isEmpty()) {
//            exifDirectory.removeField(TiffTagConstants.TIFF_TAG_ARTIST);
//            exifDirectory.add(TiffTagConstants.TIFF_TAG_ARTIST,author);
//        }
        final TiffOutputDirectory rootDirectoryt=outputSet.getOrCreateRootDirectory();
        rootDirectoryt.removeField(TiffTagConstants.TIFF_TAG_ARTIST);
        rootDirectoryt.add(TiffTagConstants.TIFF_TAG_ARTIST,"demoName");




        // 添加或更新时间信息
        if (dateTime != null && !dateTime.isEmpty()) {
            rootDirectoryt.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
            rootDirectoryt.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED);
            rootDirectoryt.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, dateTime);
            rootDirectoryt.add(ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED, dateTime);
        }

        // 写入修改后的文件
        File outputFile = new File(file.getParent(),
                file.getName().replaceFirst("\\.[^.]+$", "") + "_modified" +
                        file.getName().substring(file.getName().lastIndexOf(".")));

        try (OutputStream os = new FileOutputStream(outputFile)) {
            new ExifRewriter().updateExifMetadataLossless(file, os, outputSet);
        }

        System.out.println("EXIF信息已更新，保存到: " + outputFile.getAbsolutePath());
    }
}
